Ext.ns('journal.home');

// {{{
journal.home.EntryEditorPanel = Ext.extend(Ext.TabPanel, (function() {

    var logger = journal.LoggerFactory.getLogger("journal.home.EntryEditorPanel");

    var closeFlag = [];
    var saveMask = {};

    var getNewTitleIndex = function(scope) {
        var usedUntitled = new Array();
        var retval = -1;
        scope.items.each(function(item) {
            if (item.baseCls != 'search-results'
                    && (item.title.startsWith('untitled-') || item.title.startsWith('*untitled-'))) {
                var tabidx = item.title.substring(item.title.indexOf('-') + 1);
                usedUntitled.push(tabidx);
            }
        });

        for ( var i = 0; i <= usedUntitled.length; i++) {
            if (!journal.Utility.arrayContains(usedUntitled, i)) {
                retval = i;
                break;
            }
        }
        return retval;
    };

    return {

        // configurables
        // anything what is here can be configured from outside
        tabFlag : [],

        /** Indicator for the tab at the given index that it should always close. */
        indexStack : [],

        /** Unique ID for tabs. */
        index : 0,

        /** Unique index for new tabs, for title purpose. */
        tabId : 0,

        /** Performs the actual saving of the Entry form. */
        saveHandler : function(title, close) {
            logger.info('save.');
            saveMask.show();
            var codeForm = this.getActiveTab().get(0);
            var basicForm = codeForm.getForm();
            codeForm.setDisabled(true);
            basicForm.submit({
                params : {},
                success : function(form, a) {
                    saveMask.hide();
                    codeForm.setDisabled(false);
                    var respObj = Ext.util.JSON.decode(a.response.responseText);

                    this.tabFlag[form.findField('tabindex').getValue()] = false;

                    this.getActiveTab().setTitle(respObj.title);
                    var oldEntryId = form.findField('entryId').getValue();
                    var createNode = oldEntryId == '';
                    if (createNode) {
                        form.findField('entryId').setValue(respObj.entryId);
                        form.findField('title').setValue(respObj.title);
                        this.indexStack = journal.Utility.arrayRemove(this.indexStack, form.key + '');
                    }
                    this.callbackSaveEntry(form.findField('branchId').getValue(), respObj.entryId, respObj.title,
                            createNode);
                    var tree = Ext.getCmp(journal.Constant.Id.ENTRY_TREE);
                    this.getActiveTab().node = tree.getNodeById('l-' + respObj.entryId);

                    journal.home.MainHandler.addRecentFileItem(this.getActiveTab().node);

                    if (close) {
                        this.activeTab.fireEvent('close', this.activeTab);
                    }
                }.createDelegate(this),

                failure : function(f, a) {
                    codeForm.setDisabled(false);
                    saveMask.hide();
                    if (a.failureType === Ext.form.Action.CONNECT_FAILURE) {
                        Ext.Msg.alert('Failure', 'Server reported:' + a.response.status + ' ' + a.response.statusText);
                    } else if (a.failureType === Ext.form.Action.SERVER_INVALID) {
                        var respObj = Ext.util.JSON.decode(a.response.responseText);
                        journal.Utility.doStandardError(respObj);
                    }
                }
            });
        },

        /**
         * This is a high level function to save a tab. Title will be asked in case it is null.
         * 
         * @param close - flag to indicate of the tab should be closed after saving.
         */
        saveTab : function(close) {
            var form = this.getActiveTab().get(0);
            //var formBranchId = form.find('name', 'branchId')[0].value;
            var formEntryId = form.find('name', 'entryId')[0].value;

            if (formEntryId == null) {
                Ext.Msg.prompt('Save As', 'Title', function(btn, title) {
                    if (btn == 'ok') {
                        if (title == '') {
                            Ext.Msg.show({
                                icon : Ext.MessageBox.ERROR,
                                buttons : Ext.Msg.OK,
                                title : 'Validation Error',
                                msg : 'Title cannot be empty'
                            });
                            return;
                        }
                        form.getForm().findField('title').setValue(title);
                        this.saveHandler(title, close);
                    }
                }.createDelegate(this));
            } else {
                this.saveHandler(null, close);
            }
        },

        /** Checks if a tab panel is already loaded for a given node. */
        getNodeTab : function(node) {
            var targetTab = this.items.find(function(item) {
                return item.node == node;
            });
            return targetTab;
        },

        newTabHandler : function(node, pos) {
            if (typeof node == 'string') {
                var tree = journal.home.Main.explorerPanel.codeExplorer;
                tree.expandPath(node);
                tree.expandPath(node, 'id', function(a, targetNode) {
                    this.newTabHandler(targetNode);
                }.createDelegate(this));
                return;
            }

            closeFlag[node.id] = false;

            // band aid patch for the close tab plugin not
            // resetting the indexes.
            (function() {
                this.indexStack = [];
                this.items.each(function(item) {
                    if (item.baseCls != 'search-results' //&& item.title.startsWith('untitled-')
                    ) {
                        var tabstr = item.get(0).find('tabindex')[0].getValue();
                        var tabidx = tabstr.substring(tabstr.indexOf('-') + 1);
                        this.indexStack.push(tabidx);
                    }
                }.createDelegate(this));
            }.createDelegate(this))();

            var generateNewIndex = function() {
                for ( var i = 0; i < this.indexStack.length + 1; i++) {
                    if (!journal.Utility.arrayContains(this.indexStack, i)) {
                        this.index = i;
                        break;
                    }
                }
                this.indexStack.push(this.index);
            }.createDelegate(this);

            this.node = node;
            if (node.isLeaf()) {
                journal.StateService.add(journal.StateService.ST_TAB, node.getPath());
                journal.StateService.add(journal.StateService.ST_TABORDER, node.getPath());

                var targetTab;
                if (targetTab = this.getNodeTab(node)) {
                    this.activate(targetTab);
                    new Ext.LoadMask(this.el.dom).hide();
                    return;
                }
            } else {
                generateNewIndex();
            }

            var key = node.id.substring(0, 1) == 'b' ? this.index : node.id;
            this.tabId++;
            var codeForm = new journal.home.EntryForm({
                key : key,
                node : node
            });

            var closeTabHandler = function(p) {
                journal.StateService.remove(journal.StateService.ST_TAB, p.node.getPath());
                journal.StateService.remove(journal.StateService.ST_TABORDER, p.node.getPath());
                var tabindex = codeForm.getForm().findField('tabindex').getValue();
                this.tabFlag[tabindex] = false;
                if (codeForm.getForm().findField('title').getValue() == '') {
                    this.indexStack = journal.Utility.arrayRemove(this.indexStack, tabindex.substring(tabindex
                            .indexOf('-') + 1));
                }
                p.destroy();
                if (this.items.length == 0) {
                    Ext.getCmp('word-status').clearStatus();
                }
            }.createDelegate(this);

            var newTab = {
                node : node,
                key : key,
                title : node.isLeaf() ? node.text : 'untitled-' + getNewTitleIndex(this),
                iconCls : 'icon-note',
                items : [ codeForm ],
                anchor : '100%',
                closable : true,
                listeners : {
                    close : function(p) {
                        closeTabHandler(p);
                    },
                    remove : function(p) {
                        closeTabHandler(p);
                    },
                    resize : function(p, w, h) {
                        // TODO: Refactor
                        Ext.getCmp('word-textarea' + key).setHeight(h - 12);
                    },

                    beforeclose : function(p) {
                        var id = p.node.id;
                        if (p.title.substring(0, 1) == '*' && !closeFlag[id]) {
                            Ext.Msg.show({
                                title : 'Save Changes?',
                                msg : 'You are closing a tab that has unsaved changes. Would you like to save?',
                                buttons : Ext.Msg.YESNOCANCEL,
                                fn : function(btn) {
                                    switch (btn) {
                                    case 'cancel':
                                        break;
                                    case 'yes':
                                        journal.home.Main.editorPanel.saveTab(true);
                                        closeFlag[id] = true;
                                        break;
                                    case 'no':
                                        closeFlag[id] = true;
                                        p.fireEvent('close', p);
                                        break;
                                    }
                                },
                                animEl : 'elId',
                                icon : Ext.MessageBox.QUESTION
                            });
                            return false;
                        } else {
                            return true;
                        }
                    }

                }
            };

            var mask = new Ext.LoadMask(this.el.dom);
            mask.show();
            codeForm.setDisabled(true);
            if (pos == null) {
                pos = this.items.items.length;
            }
            this.insert(pos, newTab).show();

            if (this.getTabEl(pos) != null) {
                Ext.get(this.getTabEl(pos)).on('dblclick', function(e, t) {
                    Ext.getCmp(journal.Constant.Id.NAVPANEL).toggleCollapse();
                });
            }

            if (node.isLeaf()) {
                codeForm.load({
                    url : 'home',
                    params : {
                        action : 'getEntryDetail',
                        entryId : node.id
                    },
                    success : function(form, action) {
                        mask.hide();
                        codeForm.setDisabled(false);
                    }.createDelegate(this),
                    failure : function(resp) {
                        alert('failure on load!');
                    }
                });
            } else {
                mask.hide();
                codeForm.setDisabled(false);
            }

            var formTabIndex = codeForm.getForm().findField('tabindex').getValue();

            // NOTE: These to Ext.fly below works only when in
            // source edit mode.
            Ext.get('word-textarea' + key).on('keypress', function(e, t) {
                codeForm.undoCount = journal.home.EntryEditorHandler.editorKeyHandler(e, t, this, codeForm.undoCount);
            }.createDelegate(this));

            Ext.fly('word-textarea' + key).on('keypress', function() {
                if (!this.tabFlag[formTabIndex]) {
                    return;
                }
                var sb = Ext.getCmp('word-status');
                sb.showBusy('Saving draft...');
                (function() {
                    sb.setStatus({
                        iconCls : 'x-status-saved',
                        text : 'Draft auto-saved at ' + new Date().format('g:i:s A')
                    });
                }).defer(4000);
            }.createDelegate(this), this, {
                buffer : 5000
            // idle of 5 seconds will trigger auto save
            });
        },// eof newTabHandler()

        // {{{
        initComponent : function() {

            // hard coded config - cannot be changed from
            // outside
            var coord = new Ext.Toolbar.TextItem({
                id : 'coord',
                text : ''
            });

            var config = {
                enableTabScroll : true,
                bbar : new Ext.ux.StatusBar({
                    id : 'word-status',
                    items : [ coord, '&nbsp;' ]
                }),
                plugins : new journal.ux.TabCloseMenu(),
                listeners : {
                    render : {
                        fn : function() {
                            Ext.fly(coord.getEl().parent()).addClass('x-status-text-panel').createChild({
                                cls : 'spacer'
                            });
                        },
                        delay : 100
                    },
                    dblclick : function() {
                        alert('test');

                    }

                }
            };

            this.on('render', function() {
                saveMask = new Ext.LoadMask(this.el.dom, {
                    msg : "Saving, please wait..."
                });
            });

            // apply config
            Ext.apply(this, Ext.apply(this.initialConfig, config));

            // call parent
            journal.home.EntryEditorPanel.superclass.initComponent.apply(this, arguments);
        } // e/o function initComponent

    // }}}
    };
})()); // e/o extend

// register xtype
Ext.reg('journal.home.EntryEditorPanel', journal.home.EntryEditorPanel);
// }}}
